#![no_main]
#![no_std]

use core::{ffi::c_void, mem::MaybeUninit, ptr::null_mut};
extern crate alloc;
use mlibs::cmsis_rtos2::{
    kernel::{
        os_delay, os_kernel_initialize, os_kernel_start, system_init,
    },
    thread::{Thread, PRIORITY_HIGH, THREAD_DETACHED},
};

use mlibs::cortex_m_rt::entry;
use gpio::Led;
use log::info;
use rtt_target::{rprintln, rtt_init_print};
use mlibs::periph::flash::{self, Reset, Store};
use uart::{uart_init, uart_receive, uart_write};
mod dht11;

mod error;
mod adc;

#[derive(Debug, Clone, Copy)]
struct AppInfo {
    pub n: u32,
}

impl Reset for AppInfo {

    fn reset(&mut self) {
        self.n = 0;
    }
}
const APP_ADDR: u32 = flash::BASE_ADDR + 32 * 1024;
static mut APP_STORE: Store<AppInfo, APP_ADDR> = Store::default();

unsafe fn store_test() {
    let ret = APP_STORE.load();
    info!("load:{:#?} {}", ret, APP_STORE.n);
    APP_STORE.n += 1;
    let ret = APP_STORE.save();
    info!("save:{:#?}", ret);
}

extern "C" fn app_task_run(_: *mut c_void) {
    Led.init();
    uart_init();
    Led.ctrl_set_high();
    dht11::init();
    adc::init();
    info!("adc init succ");
    unsafe {
        UART_TASK.unsafe_new("uart_task", uart_task, null_mut());

        store_test();
    }

    loop {
        info!("adc ({},{},{})", adc::in3(), adc::in4(), adc::in5());
        os_delay(800);
        Led.ctrl_toggle();
    }
}

static mut APP_TASK: Thread<1024, PRIORITY_HIGH, THREAD_DETACHED> = Thread::default();
static mut UART_TASK: Thread<1024, PRIORITY_HIGH, THREAD_DETACHED> = Thread::default();

extern "C" fn uart_task(_: *mut c_void) {
    info!("uart task run");

    loop {
        let bw = uart_receive();
        unsafe {
            uart_write(bw);
        }
    }
}

mod gpio;
mod uart;
use embedded_alloc::LlffHeap;

#[global_allocator]
static HEAP: LlffHeap = LlffHeap::empty();

fn init_alloc() {
    const SIZE: usize = 2048;
    static mut HEAP_MEM: MaybeUninit<[u8; SIZE]> = MaybeUninit::uninit();
    unsafe {
        HEAP.init(HEAP_MEM.as_ptr() as usize, SIZE);
    }
}

#[entry]
unsafe fn main() -> ! {
    rtt_init_print!();

    init_alloc();

    system_init();
    os_kernel_initialize();

    rprintln!("app run");

    APP_TASK.unsafe_new("app_task", app_task_run, null_mut());

    os_kernel_start();
    loop {}
}

